<?php
/**
 * Zhub - A PHP Framework For API Developer
 *
 * This file is part of the Zhub package.
 *
 * (c) YiLong Fan <fantiq@163.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @author fanyilong <fantiq@163.com>
 * @copyright 2017 fanyilong. All rights reserved.
 * @package Zhub
 * @date 18-3-1
 */

namespace Zhub\Prototype\Objective\Clazz;


use Zhub\Prototype\Objective\Clazz\Exceptions\InvalidFullClassNameException;
use Zhub\Prototype\Objective\Clazz\Exceptions\InvalidNameException;

class ClazzUtil
{
    const CLASS_NAME_SPACE_SEPARATOR = '\\';

    /**
     * 这些保留关键字不能在 类名 接口名 trait名 命名空间中出现
     */
    const KEY_WORDS = ['__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor'];

    const RESERVED_WORDS = ['int','float','bool','string','true','false','null','void','iterable','object', 'resource','object','mixed','numeric'];

    const VARIABLE_PATTERN = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/i';
    /**
     * 类的常量中不能出现 这个词 其他的倒是可以的
     */
    const INVALID_CONST_NAME = 'class';

    /**
     * 对变量明 或者 函数名称合法性检查
     * @param string $name
     * @throws InvalidNameException
     */
    public static function checkName(string $name)
    {
        if (!preg_match(self::VARIABLE_PATTERN, $name)) {
            throw new InvalidNameException($name, true);
        }
    }

    public static function checkConstName(string $name)
    {
        self::checkName($name);
        if (strtolower($name) == self::INVALID_CONST_NAME) {
            throw new InvalidNameException($name);
        }
    }

    public static function checkKeyWord(string $name)
    {
        if (in_array($name, [self::KEY_WORDS, self::RESERVED_WORDS])) {
            throw new InvalidNameException($name);
        }
    }

    public static function parseClassNameSpace(string $fullClassName)
    {
        $fullClassName = trim($fullClassName, self::CLASS_NAME_SPACE_SEPARATOR);
        $idx = strrpos($fullClassName, self::CLASS_NAME_SPACE_SEPARATOR);
        if ($idx === false) {
            throw new InvalidFullClassNameException($fullClassName);
        }
        $nameSpace = substr($fullClassName, 0, $idx);
        $className = substr($fullClassName, ++$idx);
        return [$className, $nameSpace];
    }
}
